#!/bin/bash
# 该脚本用于实现 root 用户在 Linux 操作系统下的 Docker 中安装单体架构 MySQL

# 临时保存并修改语言环境
LANG_temp=$LANG
LANG=zh_CN.UTF-8

# 还原语言环境
function re_lang () {
    # 将语言环境修改回原来的值
    LANG=$LANG_temp
}

# 还原语言环境，并无异常退出
function re_lang_exit () {
    re_lang
    exit 0
}

function success_text () {
    echo -e -n "\033[32m【SUCCESS】\033[0m"
}

function warn_text () {
    echo -e -n "\033[33m【WARN】\033[0m"
}

function error_text () {
    echo -e -n "\033[31m【ERROR】\033[0m"
}

# 如果传入的目录不存在，进行目录的创建
function mkdir_404 () {
    if [ ! -d $1 ]; then
        warn_text
        echo "目录 $1 不存在，进行目录的创建..."
        mkdir -p $1
        success_text
        echo "目录 $1 创建成功"
    else
        success_text
	    echo "目录 $1 已存在，无需进行创建."
    fi
}

# 检查是否安装了社区版 Docker
is_docker_ce_install=`rpm -q docker-ce | grep '未安装软件包.*'`
if [ ${#is_docker_ce_install} -gt 0 ]; then
    error_text
    echo '还未安装社区版 Docker，请先进行安装.'
    re_lang_exit
fi

# 启动 Docker 并开启 Docker 开机自启，确保 Docker 处于运行状态
echo "Docker 启动中..."
systemctl start docker || re_lang_exit
echo "开启 Docker 开机自启中..."
systemctl enable docker || re_lang_exit

# 要进行安装的 MySQL 的版本
docker_mysql_version_default=latest
read -p "请输入要安装的 MySQL 版本(默认 $docker_mysql_version_default)：" docker_mysql_version
if [ -z "$docker_mysql_version" ]; then
    docker_mysql_version=$docker_mysql_version_default
fi

# Docker MySQL 镜像名称
# if [ "$docker_mysql_version" = "latest" ]; then
#     docker_mysql_image_name=mysql
# else
#     docker_mysql_image_name=mysql:$docker_mysql_version
# fi
docker_mysql_image_name=mysql:$docker_mysql_version

# Docker 安装 MySQL 相关映射目录和文件的家目录
docker_mysql_home_default=/home/docker/mysql
read -p "请输入 Docker 安装 MySQL 相关映射目录和文件的家目录(默认 $docker_mysql_home_default)：" docker_mysql_home
if [ -z "$docker_mysql_home" ]; then
    docker_mysql_home=$docker_mysql_home_default
fi

# 需要进行映射的目录
need_map_dir=( /log /data /conf /mysql-files /csv )

# # 目录如果不存在，进行目录的创建
mkdir_404 $docker_mysql_home
read -p "是否删除原先存在的映射目录(y-确认删除)：" -n 1 is_rm
for (( i=0; i<${#need_map_dir[*]}; i++ )); do
    if [ "$is_rm" = "y" ]; then
        # 删除原先存在的 MySQL 容器的映射目录
        rm -rf $docker_mysql_home${need_map_dir[i]}
        warn_text
        echo "已删除 $docker_mysql_home${need_map_dir[i]} 目录及其子目录和其中的文件"
    fi
    mkdir_404 $docker_mysql_home${need_map_dir[i]}
done

# 查询 Docker 中是否存在 MySQL 镜像，不存在，进行镜像的拉取
docker_mysql_image=`docker images -a | grep 'mysql' | grep "$docker_mysql_version"`
if [ -z "$docker_mysql_image" ]; then
    warn_text
    echo "Docker 中不存在 $docker_mysql_image_name 镜像"
    echo "开始拉取镜像 $docker_mysql_image_name..."
    docker pull $docker_mysql_image_name || re_lang_exit
    success_text
    echo "拉取 $docker_mysql_image_name 镜像成功"
else
    success_text
    echo "镜像 $docker_mysql_image_name 已存在，无需进行拉取"
fi

# MySQL Docker 容器名称
docker_mysql_container_name=mysql$docker_mysql_version

# 判断容器是否存在，如果存在，手动输入指定容器名称
while true; do
    if [ ! -z "`docker ps -a | grep \"$docker_mysql_container_name\"`" ]; then
        error_text
        echo "名称为 $docker_mysql_container_name 的 Docker 容器已经存在"
        read -p "请输入新 Docker 容器名称：" docker_mysql_container_name
    else
	if [ -z "$docker_mysql_container_name" ]; then
	    error_text
	    echo "Docker 容器名称不能为空."
	    read -p "请输入新 Docker 容器名称：" docker_mysql_container_name
	    continue
	fi
        break
    fi 
done

# 先运行一个 MySQL docker 容器，获取初始的配置文件后，将其删除
docker run --name $docker_mysql_container_name -d $docker_mysql_image_name || re_lang_exit
docker cp $docker_mysql_container_name:/etc/mysql $docker_mysql_home${need_map_dir[2]} || re_lang_exit
mv $docker_mysql_home${need_map_dir[2]}/mysql/* $docker_mysql_home${need_map_dir[2]}/ || re_lang_exit
docker rm -f $docker_mysql_container_name || re_lang_exit

# MySQL 容器运行时的端口，即容器的端口映射
while true; do
    read -p "请输入 MySQL 容器运行映射的端口号(默认 3306)：" mysql_port
    if [ -z "$mysql_port" ]; then
        mysql_port=3306
    fi
    # 判断端口是否被占用
    if [ ! -z "`lsof -i:$mysql_port`" ]; then
        error_text
	    echo "端口 $mysql_port 已经被占用，请选择未被占用的端口号."
    else
	break
    fi
done

# MySQL root 用户的初始密码
read -p "请输入 MySQL 数据库 root 用户的初始密码(默认 root)：" mysql_root_pwd
if [ -z "$mysql_root_pwd" ]; then
    mysql_root_pwd=root
fi

# 运行 MySQL 容器， 
docker run \
-p $mysql_port:3306 \
--name $docker_mysql_container_name \
--restart=always \
--privileged=true \
-v $docker_mysql_home/conf:/etc/mysql \
-v $docker_mysql_home/data:/var/lib/mysql \
-v $docker_mysql_home/log:/var/log/mysql \
-v $docker_mysql_home/mysql-files:/var/lib/mysql-files \
-v $docker_mysql_home/csv:/var/lib/mysql-csv \
-v /etc/localtime:/etc/localtime:ro \
-e MYSQL_ROOT_PASSWORD=$mysql_root_pwd \
-d $docker_mysql_image_name \
 || re_lang_exit

success_text
echo "MySQL 容器启动运行成功."
echo "MySQL 容器运行情况如下："
docker ps -f name=$docker_mysql_container_name

# 编写 MySQL 配置文件
echo "开始编写 MySQL 配置文件..."
echo
tee $docker_mysql_home/conf/conf.d/my.cnf <<- EOF
# MySQL 服务端的相关配置
[mysqld]
# MySQL 集群中的每个 MySQL 服务端的唯一标识
# server-id=1
# MySQL 服务端运行监听来自客户端连接的端口号
port=3306
# 是否跳过(关闭) MySQL 服务端的域名解析
# 1 表示跳过(关闭) MySQL 服务端的域名解析
skip_name_resolve=1
# MySQL 服务端关闭交互式连接前等待活动的时间
# 如果超过这个时间，客户端还未发送数据过来，服务端则会断开本次连接。
# interactive_timeout=28800
# MySQL 服务端等待来自非交互式连接的客户端的数据的最长时间
# 如果超过这个时间，客户端还未发送数据过来，服务端则会断开本次连接。
wait_timeout=300
# MySQL 服务端的默认时区
default-time_zone='+8:00'
# MySQL 服务端的默认存储引擎
default-storage-engine=InnoDB
# MySQL 服务端的字符集编码
character-set-server=utf8mb4
# MySQL 服务端的比较规则
# 要和 character-set-server 配置项配置的 MySQL 服务端的字符集编码对应
collation-server=utf8mb4_general_ci
# 客户端连接 MySQL 服务端时使用的字符集
init_connect='SET NAMES utf8mb4'
# MySQL 服务端是否对 SQL 语句大小写敏感
# 1 表示对 SQL 语句大小写不敏感
lower_case_table_names=1
# MySQL 服务端使用的默认密码校验规则插件
# MySQL 8.3.0 中“mysql_native_password”已弃用，并将在将来的版本中删除。请改用caching_sha2_password'
# default_authentication_plugin=mysql_native_password
default_authentication_plugin=caching_sha2_password
# 如果进行要进行如下配置项的配置修改，log-error 需要手动创建 error.log 文件，否则会报错，
# datadir secure_file_priv 需要在容器启动时做好目录映射，且存放数据表和数据文件的目录要保证为空，否则会报错  
# 报错日志写入位置
# log-error=/var/lib/mysql/log/error.log
# MySQL 服务端进程 ID 的存放文件及其位置
pid-file=/var/lib/mysql/mysqld.pid
# MySQL 服务端中的数据表和数据文件的存放位置
datadir=/var/lib/mysql
# MySQL 数据库中数据表中的数据导出到 csv 文件中，csv 文件的存放位置
secure_file_priv=/var/lib/mysql-csv

# 连接访问 MySQL 的客户端的相关配置
[client]
# MySQL 接收来自客户端连接访问请求时客户端使用的字符集
default-character-set=utf8mb4
EOF
success_text
echo "MySQL 配置文件编写完成."

echo "重启 MySQL 容器..."
docker restart $docker_mysql_container_name || re_lang_exit
success_text
echo "重启 MySQL 容器成功."

re_lang

